#/usr/bin/env python
#encoding: utf-8
#功能：检查syslog中的错误信息


import sys
from optparse import OptionParser
from subprocess import Popen, PIPE
import shlex
import datetime
import operator
import re

# 定义正则匹配message的log信息(时间戳 主机名 程序名 Msg)
LOG_REG = re.compile(r'(?P<logtime>\w{3}\s{1,2}\d{1,2}\s[\d:]{8})\s(?P<hostname>[\w\.]+)\s(?P<program>\w+(\[\d+\])?):\s(?P<msg>.*)')

# 定义月份英文与数字的对应关系
MONTH = {
    'Jan':1,
    'Feb':2,
    'Mar':3,
    'Apr':4,
    'May':5,
    'Jun':6,
    'Jul':7,
    'Aug':8,
    'Sep':9,
    'Oct':10,
    'Nov':11,
    'Dec':12
}

# 解析命令行选项的函数
def opt():
    parser = OptionParser('Usage: %prog [-w WARNING] [-c CRITICAL]')
    parser.add_option('-w', dest='warning', action='store', default=5, help='WARNING')
    parser.add_option('-c', dest='critical', action='store', default=10, help='CRITICAL')
    options, args = parser.parse_args()
    # 返回解析出的选项和参数
    return options, args

# 调用shell命tail来获取n行log内容
def getLog(log_file_name, line_num):
    cmd = 'tail -n %s %s' % (line_num, log_file_name)
    p = Popen(shlex.split(cmd), stdout=PIPE, stderr=PIPE)
    stdout, stderr = p.communicate()
    return stdout

# 输入每一行的内容，根据内容行首来解析出日志的时间戳
def parseLogTime(line):
    now = datetime.datetime.now()
    month, day, time = line.split()[:3]
    hour, minute, second = [int(i) for i in time.split(':')]
    logtime = datetime.datetime(now.year, MONTH[month], int(day), hour, minute, second)
    return logtime

# 字典计数(以key为索引进行累加计数)
def countDict(key, dic):
    if key in dic:
        dic[key] += 1
    else:
        dic[key] = 1

# 解析日志10分钟内的, 计算每个时间戳的日志条数
def parseLog(data):
    dic = {}
    now = datetime.datetime.now()
    ten_min_ago = now - datetime.timedelta(minutes = 10)
    data = [i for i in data.split('\n') if i]
    for line in data:
        logtime = parseLogTime(line)
        if logtime >= ten_min_ago:
            # 匹配一下正则
            match = LOG_REG.search(line)
            if match:
                match_dic = match.groupdict()
                # key是以时间戳+program为索引进行字典计数
                k = str(logtime) + ' ' + match_dic['program']
                if 'error' in match_dic['msg'].lower():
                    countDict(k, dic)
    return dic
    
# 主函数
def main():
    options, args = opt()
    # 注意这个地方要转换为int类型：因为从命令行传入时得到的是str类型
    w = int(options.warning)
    c = int(options.critical)
    # 这里设置的是10分钟
    lines = c * 600
    data = getLog('/var/log/messages', lines)
    dic =  parseLog(data)
    print dic
    # 如果日志文件是空的，没有内容，则直接返回OK即可(肯定没有错误)
    if not dic:
        print "OKOK"
        sys.exit(0)
    # 排序后，取最大记录
    sorted_dic = sorted(dic.iteritems(), key=operator.itemgetter(1), reverse=True)[0]
    # 最大时间戳记录的值
    num = sorted_dic[1]
    if num < w:
        print "OK", sorted_dic
        sys.exit(0)
    elif w <= num < c:
        print "WARNING", sorted_dic
        sys.exit(1)
    elif num >= c:
        print "CRITICAL", sorted_dic
        sys.exit(2)
    else:
        print "UNKNOWN", sorted_dic
        sys.exit(3)

# run
if __name__ == '__main__':
    main()

